package org.ms.mconf.sdk.model;

import lombok.*;
import org.micro.URL;
import org.ms.mconf.sdk.Constants;

import java.io.Serializable;
import java.util.Collection;

/**
 * The Meta Entry Model
 *
 * @author lry
 */
@Data
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class MetaConfig implements Serializable {

    /**
     * The data node name
     */
    private String node;

    /**
     * The environment name
     */
    private String environment;

    /**
     * The application name
     */
    private String application;

    /**
     * The config name
     */
    private String config;

    /**
     * The version name
     */
    private String version;

    /**
     * The build key by {@link MetaConfig}
     *
     * @param metaConfig {@link MetaConfig}
     * @return build result key
     */
    public static String buildData(String group, MetaConfig metaConfig) {
        return String.join(Constants.DELIMITER, URL.encode(group),
                URL.encode(metaConfig.getNode()),
                Constants.DATA_KEY,
                URL.encode(metaConfig.getEnvironment()),
                URL.encode(metaConfig.getApplication()),
                URL.encode(metaConfig.getConfig()),
                URL.encode(metaConfig.getVersion()));
    }

    /**
     * The parse key to {@link MetaConfig}
     *
     * @param key build key
     * @return {@link MetaConfig}
     */
    public static MetaConfig parse(String key) {
        if (key == null || key.length() == 0) {
            throw new NullPointerException("The parse key is null or length is 0");
        }

        String[] dataArray = key.split(Constants.DELIMITER);
        if (dataArray.length != 7) {
            throw new IllegalArgumentException("The parse key is illegal");
        }

        return new MetaConfig(
                URL.decode(dataArray[1]),
                URL.decode(dataArray[3]),
                URL.decode(dataArray[4]),
                URL.decode(dataArray[5]),
                URL.decode(dataArray[6]));
    }

    /**
     * The build search match key
     *
     * @param metaConfig {@link MetaConfig}
     * @return delete match key
     */
    public static String buildMatchKey(String group, MetaConfig metaConfig) {
        return String.join(Constants.DELIMITER, URL.encode(group),
                getIfNonDefault(metaConfig.getNode(), Constants.MATCH_ALL),
                Constants.DATA_KEY,
                getIfNonDefault(metaConfig.getEnvironment(), Constants.MATCH_ALL),
                getIfNonDefault(metaConfig.getApplication(), Constants.MATCH_ALL),
                getIfNonDefault(metaConfig.getConfig(), Constants.MATCH_ALL),
                getIfNonDefault(metaConfig.getVersion(), Constants.MATCH_ALL));
    }

    /**
     * The build query key
     *
     * @param metaConfig {@link MetaConfig}
     * @return key
     */
    public static String buildKey(String group, MetaConfig metaConfig) {
        return String.join(Constants.DELIMITER, URL.encode(group),
                getIfNonDefault(metaConfig.getNode(), Constants.MATCH_ALL),
                Constants.DATA_KEY,
                metaConfig.getEnvironment(),
                metaConfig.getApplication(),
                metaConfig.getConfig(),
                metaConfig.getVersion());
    }

    /**
     * The build channel key
     *
     * @param group      group id
     * @param metaConfig {@link MetaConfig}
     * @return channel key
     */
    public static String buildChannel(String group, MetaConfig metaConfig) {
        return String.join(Constants.DELIMITER, URL.encode(group),
                URL.encode(metaConfig.getNode()),
                Constants.CHANNEL_KEY,
                URL.encode(metaConfig.getEnvironment()),
                URL.encode(metaConfig.getApplication()),
                URL.encode(metaConfig.getConfig()),
                URL.encode(metaConfig.getVersion()));
    }

    /**
     * The parse key to {@link MetaConfig}
     *
     * @param key build key
     * @return {@link MetaConfig}
     */
    public static MetaConfig parseChannel(String key) {
        return parse(key);
    }

    private static String getIfNonDefault(String value, String defaultValue) {
        return (value == null || value.length() == 0) ? defaultValue : value;
    }

    /**
     * The check not blank
     *
     * @param metaConfig {@link MetaConfig}
     */
    public static void checkNotBlank(MetaConfig metaConfig) {
        if (metaConfig == null
                || metaConfig.getNode() == null || metaConfig.getNode().length() == 0
                || metaConfig.getEnvironment() == null || metaConfig.getEnvironment().length() == 0
                || metaConfig.getApplication() == null || metaConfig.getApplication().length() == 0
                || metaConfig.getConfig() == null || metaConfig.getConfig().length() == 0
                || metaConfig.getVersion() == null || metaConfig.getVersion().length() == 0) {
            throw new NullPointerException();
        }
    }

}